package com.funcablaze.component.control;

import com.funcablaze.component.view.BaseLayout;
import com.funcablaze.component.view.Component;
import com.funcablaze.component.view.View;
import com.funcablaze.func.AttributeConverter;
import com.funcablaze.func.Color;
import com.funcablaze.func.parser.XML;
import org.xml.sax.SAXException;

import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import static com.funcablaze.func.parser.XML.SceneParser.ViewPath;

public class Theme {
	
	public static Map<Class<? extends Component>, StyleStruct> themeLight = new HashMap<>();
	public static Map<Class<? extends Component>, StyleStruct> themeNight = new HashMap<>();
	public static Map<Class<? extends Component>, StyleStruct> themeDefault = new HashMap<>();
	
	public static class StyleStruct {
		public Color backgroundColor = new Color("#fff");
		public Color textColor = new Color("#000");
		public int textSize = 15;
		public String textFontFamily = "Arial";
		public BaseLayout.TextAlign textAlign = BaseLayout.TextAlign.Left;
		
		public void setBackgroundColor(String hex) {
			backgroundColor = new Color(hex);
		}
		public void setTextColor(String hex) {
			textColor = new Color(hex);
		}
		public void setTextSize(String textSize) {
			this.textSize = Integer.parseInt(textSize);
		}
		public void setTextFont(String textFontFamily) {
			this.textFontFamily = textFontFamily;
		}
		public void setTextAlign(String textAlign) {
			switch (textAlign) {
				case "left", "Left":
					this.textAlign = BaseLayout.TextAlign.Left;
					break;
				case "center", "Center":
					this.textAlign = BaseLayout.TextAlign.Center;
					break;
				case "right", "Right":
					this.textAlign = BaseLayout.TextAlign.Right;
					break;
			}
		}
		protected String capitalize(String fieldName) {
			return fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
		}
	}
	
	/**
	 * 从XML文件中加载主题
	 * @param name XML文件名
	 */
	public static void inflateXML(String name) throws IOException, ClassNotFoundException, ParserConfigurationException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchMethodException, SAXException {
		InputStream is = View.class.getResourceAsStream(name);
		XML.ThemeParser.parser(is);
	}
	
	/**
	 * 从XML文件中加载主题
	 * @param name XML文件名
	 */
	public static void inflateCSS(String name) throws IOException {
		throw new UnsupportedOperationException("暂不支持 CSS 文件的解析");
//		URL url = Scene2D.class.getResource(name);
//		CSS.ThemeParser.parser();
	}
	
	/**
	 * 应用主题
	 * @param type 主题类型 Light, Dark, Default
	 * @param map  主题键值对
	 */
	public static void apply(String type, String name, Map<String, String> map) {
		ThemeType t = ThemeType.Default;
		switch (type) {
			case "Light", "light":
				t = ThemeType.Light;
				break;
			case "Dark", "dark":
				t = ThemeType.Dark;
				break;
			case "Default", "default":
				break;
			default:
				throw new IllegalArgumentException("不支持的主题类型 " + type);
		}
		StyleStruct styleStruct = new StyleStruct();
		Class<? extends Component> component = Component.class;
		if (name == null) {
			throw new IllegalArgumentException("用于指定作用范围的 name 不能为空");
		} else if (!name.equals("global")) {
				try {
					Class<?> aClass = Class.forName(name.contains(".") ? name : ViewPath + name);
					if (Component.class.isAssignableFrom(aClass)) {
						component = (Class<? extends Component>) aClass;
					} else {
						throw new IllegalArgumentException("类 " + name + " 不是 Component 的子类");
					}
				} catch (ClassNotFoundException e) {
					throw new IllegalArgumentException("类 " + name + " 不存在");
				}
		}
		
		for (Map.Entry<String, String> entry : map.entrySet()) {
			String key = entry.getKey();
			String value = entry.getValue();
			try {
				// 转换命名风格：background-color -> backgroundColor
				String fieldName = AttributeConverter.toCamelCase(key);
				
				// 优先使用setter方法
				String setterName = "set" + styleStruct.capitalize(fieldName);
				Method setter = AttributeConverter.findSetter(StyleStruct.class, setterName, value);
				
				if (setter != null) {
					Class<?> paramType = setter.getParameterTypes()[0];
					Object converted = AttributeConverter.convert(value, paramType);
					setter.invoke(styleStruct, converted);
				} else {
					// Fallback到字段反射
					Field field = StyleStruct.class.getDeclaredField(fieldName);
					field.setAccessible(true);
					Object converted = AttributeConverter.convert(value, field.getType());
					field.set(styleStruct, converted);
				}
			} catch (Exception e) {
				AttributeConverter.handleError(key, value, e);
			}
		}
		switch (t) {
			case Default:
				themeDefault.put(component, styleStruct);
				break;
			case Light:
				themeLight.put(component, styleStruct);
				break;
			case Dark:
				themeNight.put(component, styleStruct);
				break;
		}
	}
	
	/**
	 * 主题类型
	 */
	public enum ThemeType {
		Default,
		Light,
		Dark
	}
}
